package cn.x.utils;

import java.text.DecimalFormat;
import java.util.Arrays;
/**
 * @author a tester
 * @date 2021/5/16
 */
public class RandomBankcardNo {

    public static String getBankCardNo(String bankCode) {
        bankCode = bankCode.toUpperCase();
        switch(bankCode){
            case "ABC": return ccngen("622848001009xxxxxxx",9999);
            case "CCB": return ccngen("622700247017xxxxxxx",9999);
            case "BCOM": return ccngen("622262025000xxxxxxx",9999);
            case "BOC": return ccngen("621785700001xxxxxxx",9999);
            case "PAB": return ccngen("623058300001xxxxxxx",9999);
            case "CMB": return ccngen("621483021xxxxxxx",9999);
            case "SPDB": return ccngen("621792011xxxxxxx",9999);
            case "CIB": return ccngen("62290933726xxxxxxx",9999);
            case "CGB": return ccngen("621462052100xxxxxxx",9999);
            case "CITIC": return ccngen("621771070xxxxxxx",9999);
            case "HXB": return ccngen("623020084xxxxxxx",9999);
            case "CMBC": return ccngen("622617310xxxxxxx",9999);
            case "CEB": return ccngen("622662300xxxxxxx",9999);
            case "PSBC": return ccngen("621799290001xxxxxxx",9999);
            default: return ccngen("622202360547xxxxxxx",9999); //ICBC
        }
    }


    private static String ccngen(String pattern, int tryTimes) {
        boolean genSuccess = false;
        String validCardNo = "";
        for (int i = 0; i < tryTimes; i++) {
            String randomSevenNum = new DecimalFormat("0000000").format(Math.random() * 10000000);
            String testCardNo = "";
            if (pattern.contains("xxxxxxx")) {
                testCardNo = pattern.replaceAll("x", "") + randomSevenNum;
            } else {
                testCardNo = pattern;
            }
            if (chkLCD(testCardNo) && chkCCCksum(testCardNo)) {
                genSuccess = true;
                validCardNo = testCardNo;
                break;
            }

            if (!pattern.contains("xxxxxxx")) {
                break;
            }
        }
        if (genSuccess) {
            return validCardNo;
        } else {
            throw new RuntimeException("genCardNoFailed!");
            //return "genCardNoFailed!";
        }
    }


    private static boolean chkCCCksum(String cf) {
        boolean r = false;
        String w = "21";
        String ml = "";
        int j = 1;
        for (int i = 1; i <= cf.length() - 1; i++) {
            int m = Integer.valueOf(midS(cf, i, 1)) * Integer.valueOf(midS(w, j, 1));
            m = Integer.valueOf(sumDigits(String.valueOf(m), 1));
            ml += "" + m;
            j++;
            if (j > w.length()) {
                j = 1;
            }
        }
        int ml2 = Integer.valueOf(sumDigits(ml, -1));
        int ml1 = (Integer.valueOf(sumDigits(String.valueOf(ml2), -1)) * 10 - ml2) % 10;
        if (ml1 == rightS(cf, 1)) {
            r = true;
        }
        return r;
    }


    private static int rightS(String aS, int n) {
        String rS = "";
        if (n >= 1) {
            rS = aS.substring(aS.length() - n, aS.length());
        }
        return Integer.valueOf(rS);
    }


    private static String sumDigits(String n, int m) {
//		  if (m == 0 ) {
//		        m = 1;
//		    }
        int r = 0;
        if (m > 0) {
            while (n.length() > m) {
                for (int i = 1; i <= n.length(); i++) {
                    r += Integer.valueOf(midS(n, i, 1));
                }
                n = "" + r;
            }
        } else {
            for (int j = 1; j <= Math.abs(m); j++) {
                for (int i = 1; i <= n.length(); i++) {
                    r += Integer.valueOf(midS(n, i, 1));
                }
                n = "" + r;
            }
        }
//		    r = n;
        return n;
    }


    private static boolean chkLCD(String cf) {
        boolean r = false;
        cf += "";
        boolean bl = isdiv(cf.length(), 2);
        int ctd = 0;
        for (int i = 1; i <= cf.length(); i++) {
            int cdg = Integer.valueOf(midS(cf, i, 1));
            if (isdiv(i, 2) != bl) {
                cdg *= 2;
                if (cdg > 9) {
                    cdg -= 9;
                }
            }
            ctd += cdg * 1.0;
        }
        if (isdiv(ctd, 10)) {
            r = true;
        }
        return r;
    }


    private static boolean isdiv(int a, int b) {
/*        double aa = a * 1.0;
        double bb = b * 1.0;
        boolean r = false;
        if (aa / bb == Math.floor(aa / bb)) {
            r = true;
        }
        return r;*/
        return a % b == 0;
    }


    private static String sbtStringSpRnd(String s1, String s2, String bS) {
        if (bS == "") {
            bS = "0123456789";
        }
        String ous = "";
        bS += "";
        for (int i = 1; i <= s1.length(); i++) {
            String c1 = s1.substring(i - 1, i);
            int c2 = s2.indexOf(c1);
            if (c2 == -1) {
                ous += c1;
            } else {
                ous += midS(bS, (int) Math.floor(Math.random() * (bS.length() - 1)) + 1, 1);
            }
        }
        return ous;
    }


    private static String chkCard(String cdi) {
        cdi += "";
        int ccn = 0;
        String cn = "unknown";
        String cf = sbtString(cdi, " -/abcdefghijklmnopqrstuvwyzABCDEFGHIJLMNOPQRSTUVWYZ");
        if (leftS(cf, 1) == "4") {
            cf = leftS(cf, 8);
        }
        String[] c = {"", "622202360547xxxxxxx", "622617310xxxxxxx"};
        String[] cd = {"", "工商银行", "民生银行"};
        for (int i = 1; i <= 2; i++) {
            String cct = sbtString(c[i], " -/abcdefghijklmnopqrstuvwyzABCDEFGHIJLMNOPQRSTUVWYZ");
            if (leftS(cf, 1) == "4") {
                cct = leftS(cct, 8);
            }
            boolean ccc = cmpPattern(cf, cct);
            if (ccc) {
                ccn = i;
                break;
            }
        }
        if (ccn > 0) {
            cn = cd[ccn];
        }
        return cn;
    }

    private static String sbtString(String s1, String s2) {
        String ous = "";
        s1 += "";
        s2 += "";
        for (int i = 1; i <= s1.length(); i++) {
            String c1 = s1.substring(i - 1, i);
            int c2 = s2.indexOf(c1);
            if (c2 == -1) {
                ous += c1;
            }
        }
        return ous;
    }

    private static String leftS(String as, int n) {
        as += "";
        String rS = "";
        if (n >= 1) {
            rS = as.substring(0, n);
        }
        return rS;
    }

    private static boolean cmpPattern(String a, String p) {
        String x = null;
        if (x == "" || x == null) {
            x = "x";
        }
        x = "" + x.substring(0, 1);
        a += "";
        p += "";
        boolean r = false;
        int mc = 0;
        if (a.length() == p.length()) {
            for (int i = 1; i <= a.length(); i++) {
                String a1 = midS(a, i, 1);
                String p1 = midS(p, i, 1);
                if (a1 == p1 || p1 == x) {
                    mc++;
                }
            }
        }
        if (mc == a.length()) {
            r = true;
        }
        return r;
    }


    private static String midS(String aS, int n, int n2) {
        aS += "";
        String rS = "";
        n *= 1;
        n2 *= 1;
        if (n < 0) {
            n++;
        }
        rS = aS.substring(n - 1, n - 1 + n2);
        return rS;
    }

    public static void main(String[] args) {
        String[] bankCodes = ",ICBC,ABC,CCB,BCOM,BOC,PAB,CMB,SPDB,CIB,CGB,CITIC,HXB,CMBC,CEB,PSBC".split(",");
        System.out.println(Arrays.toString(bankCodes));
        Arrays.stream(bankCodes).forEach(e -> {
            System.out.println(e);
            System.out.println(getBankCardNo(e));
        });

    }
}
